# _*_ coding: utf-8 _*_
# .@FileName:C04_01_Group
# .@Data....:2025-03-09 : 18 : 50
# .@Aurhor..:LiuJingYu
"""
launch:
from __future__ import unicode_literals, print_function
import maya.cmds as mc
"""
import maya.cmds as cmds
from typing import Optional


def create_group_if_not_exists(group_name: str, parent: Optional[str] = None) -> str:
    """
    检查指定名称的组是否存在，如果不存在则创建该组，并可指定其父组。

    :param group_name: 要创建或检查的组的名称
    :param parent: 可选参数，指定新创建组的父组，类型为字符串，若不指定则为 None
    :return: 组的名称，类型为字符串
    """
    if not cmds.objExists(group_name):
        if parent:
            return cmds.group(empty=True, name=group_name, parent=parent)
        return cmds.group(empty=True, name=group_name)
    return group_name


def create_group_structure() -> tuple[str, str, str]:
    """
    创建组结构：master -> geometry, controls

    :return: 包含 controls 组、geometry 组和 master 组名称的元组，每个元素类型为字符串
    """
    master_group = create_group_if_not_exists('master')
    geometry_group = create_group_if_not_exists('geometry', master_group)
    controls_group = create_group_if_not_exists('controls', master_group)

    # 在 master 下创建 rigNodes 和 joints 组
    rigNodes_group = create_group_if_not_exists('rigNodes', master_group)
    joints_group = create_group_if_not_exists('joints', master_group)

    # 在 rigNodes 组下创建 rigNodesLocal 和 rigNodesWorld 组
    rigNodesLocal_group = create_group_if_not_exists('rigNodesLocal', rigNodes_group)
    rigNodesWorld_group = create_group_if_not_exists('rigNodesWorld', rigNodes_group)

    print("组结构创建完成：master -> geometry, controls, rigNodes -> rigNodesLocal, rigNodesWorld; joints")
    return controls_group, geometry_group, master_group


def create_and_setup_controller(controls_group: str) -> str:
    """
    创建一个曲线圆作为控制器，设置颜色，创建零组并进行分组操作。

    :param controls_group: 控制器所在的 controls 组的名称，类型为字符串
    :return: 控制器的名称，类型为字符串
    """
    # 创建一个曲线圆作为控制器
    circle_ctrl = cmds.circle(nr=(0, 1, 0), r=1, name='ctrl_m_world_001')[0]

    # 设置曲线颜色为黄色
    # 在 Maya 中，颜色索引 17 代表黄色
    cmds.setAttr(f"{circle_ctrl}.overrideEnabled", 1)
    cmds.setAttr(f"{circle_ctrl}.overrideColor", 17)




    # 在原点创建一个名为 zero_m_world_001 的组
    zero_group = create_group_if_not_exists('zero_m_world_001')

    # 将控制器放入 zero_m_world_001 组里
    cmds.parent(circle_ctrl, zero_group)

    # 将 zero_m_world_001 组放入 controls 组里
    cmds.parent(zero_group, controls_group)

    print("操作完成：创建了控制器并完成分组设置。")
    return circle_ctrl


def create_new_group_and_constrain(circle_ctrl: str, geometry_group: str) -> None:
    """
    在 geometry 组下创建新组 trans_m_high_world_001，并进行约束操作。

    :param circle_ctrl: 控制器的名称，类型为字符串
    :param geometry_group: geometry 组的名称，类型为字符串
    """
    # 在 geometry 组下创建一个新组，命名为 trans_m_high_world_001
    trans_group = create_group_if_not_exists('trans_m_high_world_001', geometry_group)

    # 进行父子约束
    cmds.parentConstraint(circle_ctrl, trans_group, mo=False)

    # 进行缩放约束
    cmds.scaleConstraint(circle_ctrl, trans_group, mo=False)

    print("操作完成：在 geometry 组下创建新组并完成约束设置。")


def setup_custom_scale_attribute(circle_ctrl: str) -> None:
    """
    在 circle_ctrl 上创建自定义浮点属性 rigScale 并关联 scale 属性，隐藏 scale 和 visibility 属性。

    :param circle_ctrl: 控制器的名称，类型为字符串
    """
    # 创建自定义浮点属性 rigScale
    if not cmds.attributeQuery('rigScale', node=circle_ctrl, exists=True):
        cmds.addAttr(circle_ctrl, longName='rigScale', attributeType='float', defaultValue=1.0, minValue=0,
                     keyable=True)

    # 关联 rigScale 到 scale 属性的三个值
    for axis in ['X', 'Y', 'Z']:
        cmds.connectAttr(f'{circle_ctrl}.rigScale', f'{circle_ctrl}.scale{axis}')

    # 隐藏 scale 属性
    for axis in ['X', 'Y', 'Z']:
        cmds.setAttr(f'{circle_ctrl}.scale{axis}', keyable=False, channelBox=False)

    # 隐藏 visibility 属性
    cmds.setAttr(f'{circle_ctrl}.visibility', keyable=False, channelBox=False)

    print("操作完成：创建自定义属性并关联、隐藏 scale 和 visibility 属性。")


def add_enum_attribute(node: str, attr_name: str, enum_values: str, show_in_channel_box: bool = True) -> None:
    """
    在指定节点上添加枚举属性，并可选择是否显示在通道盒中。

    :param node: 要添加属性的节点名称，类型为字符串
    :param attr_name: 要添加的枚举属性的名称，类型为字符串
    :param enum_values: 枚举属性的取值列表，用冒号分隔，类型为字符串
    :param show_in_channel_box: 可选参数，是否将属性显示在通道盒中，默认为 True，类型为布尔值
    """
    if not cmds.attributeQuery(attr_name, node=node, exists=True):
        cmds.addAttr(node, longName=attr_name, attributeType='enum', enumName=enum_values, keyable=False)
    if show_in_channel_box:
        cmds.setAttr(f'{node}.{attr_name}', channelBox=True)


def hide_default_attributes(node: str, attributes: list[str]) -> None:
    """
    隐藏指定节点上的默认属性。

    :param node: 要隐藏属性的节点名称，类型为字符串
    :param attributes: 要隐藏的属性名称列表，列表元素类型为字符串
    """
    for attr in attributes:
        cmds.setAttr(f'{node}.{attr}', keyable=False, channelBox=False)


def setup_master_custom_attributes(master_group: str, geometry_group: str, controls_group: str) -> None:
    """
    在 master_group 上添加自定义枚举属性并进行关联，让属性显示在通道盒中，隐藏默认属性。

    :param master_group: master 组的名称，类型为字符串
    :param geometry_group: geometry 组的名称，类型为字符串
    :param controls_group: controls 组的名称，类型为字符串
    """
    # 添加 Geometry_Vis 枚举属性
    add_enum_attribute(master_group, 'Geometry_Vis', 'off:on')
    # 关联 Geometry_Vis 到 geometry_group 的 visibility 上
    cmds.connectAttr(f'{master_group}.Geometry_Vis', f'{geometry_group}.visibility')

    # 添加 Control_Vis 枚举属性
    add_enum_attribute(master_group, 'Control_Vis', 'off:on')
    # 关联 Control_Vis 到 controls_group 的 visibility 上
    cmds.connectAttr(f'{master_group}.Control_Vis', f'{controls_group}.visibility')

    # 添加 Geometry_Disiplay_Type 枚举属性
    add_enum_attribute(master_group, 'Geometry_Disiplay_Type', 'Normal:Template:Reference')
    # 设置 geometry_group 的 overrideEnabled 属性为 1
    cmds.setAttr(f'{geometry_group}.overrideEnabled', 1)
    # 关联 Geometry_Disiplay_Type 到 geometry_group 的 overrideDisplayType 属性
    cmds.connectAttr(f'{master_group}.Geometry_Disiplay_Type', f'{geometry_group}.overrideDisplayType')

    # 添加 Resolution 枚举属性
    add_enum_attribute(master_group, 'Resolution', 'Hight:mid')

    # 添加 Joint_Vis 枚举属性
    add_enum_attribute(master_group, 'Joint_Vis', 'off:on')

    # 添加 Rig_Nodes_Vis 枚举属性
    add_enum_attribute(master_group, 'Rig_Nodes_Vis', 'off:on')

    # 隐藏 master 通道盒里的位移、旋转、缩放和可见性属性
    default_attributes = ['translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY', 'rotateZ', 'scaleX', 'scaleY',
                          'scaleZ', 'visibility']
    hide_default_attributes(master_group, default_attributes)

    print("操作完成：在 master 组上添加自定义枚举属性并完成关联，属性显示在通道盒，隐藏默认属性。")


def add_constraints_to_new_groups(circle_ctrl: str):
    """
    使用 ctrl_m_world_001 对 rigNodesLocal 与 joints 分别进行父子约束和缩放约束。
    :param circle_ctrl: 控制器的名称，类型为字符串
    """
    rigNodesLocal_group = 'rigNodesLocal'
    joints_group = 'joints'

    # 对 rigNodesLocal 进行父子约束和缩放约束
    cmds.parentConstraint(circle_ctrl, rigNodesLocal_group, mo=False)
    cmds.scaleConstraint(circle_ctrl, rigNodesLocal_group, mo=False)

    # 对 joints 进行父子约束和缩放约束
    cmds.parentConstraint(circle_ctrl, joints_group, mo=False)
    cmds.scaleConstraint(circle_ctrl, joints_group, mo=False)

    print("操作完成：ctrl_m_world_001 对 rigNodesLocal 与 joints 分别进行父子约束和缩放约束。")


if __name__ == "__main__":
    # 创建组结构
    controls_group, geometry_group, master_group = create_group_structure()
    # 创建并设置控制器
    circle_ctrl = create_and_setup_controller(controls_group)
    # 创建新组并进行约束操作
    create_new_group_and_constrain(circle_ctrl, geometry_group)
    # 设置自定义缩放属性
    setup_custom_scale_attribute(circle_ctrl)
    # 设置 master 组的自定义枚举属性并关联
    setup_master_custom_attributes(master_group, geometry_group, controls_group)
    # 对新创建的组添加约束
    add_constraints_to_new_groups(circle_ctrl)
